#include "application_manager.h"
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QStandardPaths>
#include <QProcess>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QStringList>
#include <QList>

#ifdef Q_OS_WIN
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <winreg.h>
#include <shlobj.h>
#include <shellapi.h>
#include <winver.h>
#endif

ApplicationManager::ApplicationManager(QObject *parent)
    : QObject(parent)
    , m_refreshTimer(nullptr)
{
    // 创建刷新定时�?
    m_refreshTimer = new QTimer(this);
    connect(m_refreshTimer, &QTimer::timeout, this, &ApplicationManager::onRefreshTimer);
    
    // 初始扫描
    refreshApplicationList();
    
    // 启动定时刷新（每30秒）
    m_refreshTimer->start(30000);
}

ApplicationManager::~ApplicationManager()
{
    if (m_refreshTimer) {
        m_refreshTimer->stop();
    }
}

QStringList ApplicationManager::getApplicationList()
{
    return m_installedApplications;
}

bool ApplicationManager::launchApplication(const QString &exePath)
{
    if (exePath.isEmpty() || !QFileInfo::exists(exePath)) {
        qWarning() << "应用程序路径不存�?" << exePath;
        emit applicationLaunched(exePath, false);
        return false;
    }
    
    QProcess *process = new QProcess(this);
    process->setProgram(exePath);
    
    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
            [this, exePath, process](int exitCode, QProcess::ExitStatus exitStatus) {
                Q_UNUSED(exitCode)
                Q_UNUSED(exitStatus)
                process->deleteLater();
            });
    
    bool success = process->startDetached();
    if (success) {
        qDebug() << "应用程序启动成功:" << exePath;
        emit applicationLaunched(exePath, true);
    } else {
        qWarning() << "应用程序启动失败:" << exePath;
        emit applicationLaunched(exePath, false);
    }
    
    return success;
}

bool ApplicationManager::isApplicationRunning(const QString &exePath)
{
    QString processName = QFileInfo(exePath).baseName();
    return m_runningProcesses.contains(processName, Qt::CaseInsensitive);
}

void ApplicationManager::refreshApplicationList()
{
    scanInstalledApplications();
    scanRunningProcesses();
    emit applicationListUpdated();
}

QStringList ApplicationManager::getRunningProcesses()
{
    return m_runningProcesses;
}

bool ApplicationManager::terminateProcess(const QString &processName)
{
#ifdef Q_OS_WIN
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return false;
    }
    
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    
    bool found = false;
    if (Process32First(hSnapshot, &pe)) {
        do {
            QString currentProcessName = QString::fromWCharArray(pe.szExeFile);
            if (currentProcessName.compare(processName, Qt::CaseInsensitive) == 0) {
                HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
                if (hProcess) {
                    if (TerminateProcess(hProcess, 0)) {
                        found = true;
                        qDebug() << "进程已终�?" << processName;
                        emit applicationTerminated(processName, true);
                    }
                    CloseHandle(hProcess);
                }
            }
        } while (Process32Next(hSnapshot, &pe));
    }
    
    CloseHandle(hSnapshot);
    return found;
#else
    Q_UNUSED(processName)
    return false;
#endif
}

bool ApplicationManager::terminateProcessByPid(qint64 pid)
{
#ifdef Q_OS_WIN
    HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, static_cast<DWORD>(pid));
    if (hProcess) {
        bool success = TerminateProcess(hProcess, 0);
        CloseHandle(hProcess);
        return success;
    }
    return false;
#else
    Q_UNUSED(pid)
    return false;
#endif
}

void ApplicationManager::onRefreshTimer()
{
    refreshApplicationList();
}

void ApplicationManager::scanInstalledApplications()
{
    m_installedApplications.clear();
    
#ifdef Q_OS_WIN
    // 扫描注册表中的已安装程序
    HKEY hKey;
    LONG result;
    
    // 扫描64位程�?
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
                         L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
                         0, KEY_READ, &hKey);
    
    if (result == ERROR_SUCCESS) {
        DWORD index = 0;
        WCHAR subKeyName[256];
        DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(WCHAR);
        
        while (RegEnumKeyEx(hKey, index, subKeyName, &subKeyNameSize, 
                           nullptr, nullptr, nullptr, nullptr) == ERROR_SUCCESS) {
            
            HKEY hSubKey;
            if (RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS) {
                
                // 获取显示名称
                WCHAR displayName[256];
                DWORD displayNameSize = sizeof(displayName);
                if (RegQueryValueEx(hSubKey, L"DisplayName", nullptr, nullptr,
                                   reinterpret_cast<LPBYTE>(displayName), &displayNameSize) == ERROR_SUCCESS) {
                    
                    // 获取安装路径
                    WCHAR installLocation[512];
                    DWORD installLocationSize = sizeof(installLocation);
                    if (RegQueryValueEx(hSubKey, L"InstallLocation", nullptr, nullptr,
                                       reinterpret_cast<LPBYTE>(installLocation), &installLocationSize) == ERROR_SUCCESS) {
                        
                        QString appName = QString::fromWCharArray(displayName);
                        QString appPath = QString::fromWCharArray(installLocation);
                        
                        // 跳过系统程序
                        if (!appName.contains("Windows", Qt::CaseInsensitive) &&
                            !appName.contains("Microsoft", Qt::CaseInsensitive) &&
                            !appName.contains("Update", Qt::CaseInsensitive)) {
                            
                            // 查找exe文件
                            QDir appDir(appPath);
                            QStringList exeFiles = appDir.entryList(QStringList() << "*.exe", QDir::Files);
                            
                            if (!exeFiles.isEmpty()) {
                                QString fullPath = appDir.absoluteFilePath(exeFiles.first());
                                m_installedApplications.append(fullPath);
                            }
                        }
                    }
                }
                
                RegCloseKey(hSubKey);
            }
            
            index++;
            subKeyNameSize = sizeof(subKeyName) / sizeof(WCHAR);
        }
        
        RegCloseKey(hKey);
    }
    
    // 扫描32位程�?
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
                         L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
                         0, KEY_READ, &hKey);
    
    if (result == ERROR_SUCCESS) {
        DWORD index = 0;
        WCHAR subKeyName[256];
        DWORD subKeyNameSize = sizeof(subKeyName) / sizeof(WCHAR);
        
        while (RegEnumKeyEx(hKey, index, subKeyName, &subKeyNameSize, 
                           nullptr, nullptr, nullptr, nullptr) == ERROR_SUCCESS) {
            
            HKEY hSubKey;
            if (RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS) {
                
                // 获取显示名称
                WCHAR displayName[256];
                DWORD displayNameSize = sizeof(displayName);
                if (RegQueryValueEx(hSubKey, L"DisplayName", nullptr, nullptr,
                                   reinterpret_cast<LPBYTE>(displayName), &displayNameSize) == ERROR_SUCCESS) {
                    
                    // 获取安装路径
                    WCHAR installLocation[512];
                    DWORD installLocationSize = sizeof(installLocation);
                    if (RegQueryValueEx(hSubKey, L"InstallLocation", nullptr, nullptr,
                                       reinterpret_cast<LPBYTE>(installLocation), &installLocationSize) == ERROR_SUCCESS) {
                        
                        QString appName = QString::fromWCharArray(displayName);
                        QString appPath = QString::fromWCharArray(installLocation);
                        
                        // 跳过系统程序
                        if (!appName.contains("Windows", Qt::CaseInsensitive) &&
                            !appName.contains("Microsoft", Qt::CaseInsensitive) &&
                            !appName.contains("Update", Qt::CaseInsensitive)) {
                            
                            // 查找exe文件
                            QDir appDir(appPath);
                            QStringList exeFiles = appDir.entryList(QStringList() << "*.exe", QDir::Files);
                            
                            if (!exeFiles.isEmpty()) {
                                QString fullPath = appDir.absoluteFilePath(exeFiles.first());
                                if (!m_installedApplications.contains(fullPath)) {
                                    m_installedApplications.append(fullPath);
                                }
                            }
                        }
                    }
                }
                
                RegCloseKey(hSubKey);
            }
            
            index++;
            subKeyNameSize = sizeof(subKeyName) / sizeof(WCHAR);
        }
        
        RegCloseKey(hKey);
    }
    
    // 扫描开始菜单程�?
    QStringList startMenuPaths = {
        QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation),
        QDir::homePath() + "/AppData/Roaming/Microsoft/Windows/Start Menu/Programs",
        "C:/ProgramData/Microsoft/Windows/Start Menu/Programs"
    };
    
    for (const QString &path : startMenuPaths) {
        QDir dir(path);
        if (dir.exists()) {
            QStringList exeFiles;
            QDirIterator it(path, QStringList() << "*.exe", QDir::Files, QDirIterator::Subdirectories);
            while (it.hasNext()) {
                exeFiles.append(it.next());
            }
            for (const QString &exeFile : exeFiles) {
                QString fullPath = dir.absoluteFilePath(exeFile);
                if (!m_installedApplications.contains(fullPath)) {
                    m_installedApplications.append(fullPath);
                }
            }
        }
    }
    
    qDebug() << QString("扫描�?%1 个已安装应用程序").arg(m_installedApplications.size());
#endif
}

void ApplicationManager::scanRunningProcesses()
{
    m_runningProcesses.clear();
    m_processList.clear();
    
#ifdef Q_OS_WIN
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return;
    }
    
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    
    if (Process32First(hSnapshot, &pe)) {
        do {
            QString processName = QString::fromWCharArray(pe.szExeFile);
            QString exePath = getProcessExePath(pe.th32ProcessID);
            
            ProcessInfo info;
            info.pid = pe.th32ProcessID;
            info.name = processName;
            info.exePath = exePath;
            info.windowTitle = getProcessWindowTitle(pe.th32ProcessID);
            
            m_processList.append(info);
            m_runningProcesses.append(processName);
            
        } while (Process32Next(hSnapshot, &pe));
    }
    
    CloseHandle(hSnapshot);
#endif
}

QString ApplicationManager::getProcessExePath(DWORD processId)
{
#ifdef Q_OS_WIN
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
    if (hProcess) {
        WCHAR exePath[MAX_PATH];
        DWORD pathLength = MAX_PATH;
        
        if (QueryFullProcessImageName(hProcess, 0, exePath, &pathLength)) {
            CloseHandle(hProcess);
            return QString::fromWCharArray(exePath);
        }
        
        CloseHandle(hProcess);
    }
#endif
    return QString();
}

QString ApplicationManager::getProcessWindowTitle(DWORD processId)
{
#ifdef Q_OS_WIN
    HWND hwnd = nullptr;
    do {
        hwnd = FindWindowEx(nullptr, hwnd, nullptr, nullptr);
        DWORD windowProcessId;
        GetWindowThreadProcessId(hwnd, &windowProcessId);
        
        if (windowProcessId == processId && IsWindowVisible(hwnd)) {
            WCHAR windowTitle[256];
            GetWindowText(hwnd, windowTitle, 256);
            QString title = QString::fromWCharArray(windowTitle);
            if (!title.isEmpty()) {
                return title;
            }
        }
    } while (hwnd);
#endif
    return QString();
}

QString ApplicationManager::getApplicationName(const QString &exePath)
{
    QFileInfo fileInfo(exePath);
    return fileInfo.baseName();
}

QString ApplicationManager::getApplicationVersion(const QString &exePath)
{
#ifdef Q_OS_WIN
    DWORD versionInfoSize = GetFileVersionInfoSize(reinterpret_cast<LPCWSTR>(exePath.utf16()), nullptr);
    if (versionInfoSize > 0) {
        QByteArray versionInfo(versionInfoSize, 0);
        if (GetFileVersionInfo(reinterpret_cast<LPCWSTR>(exePath.utf16()), 0, versionInfoSize, versionInfo.data())) {
            VS_FIXEDFILEINFO *fileInfo;
            UINT fileInfoSize;
            if (VerQueryValue(versionInfo.data(), L"\\", reinterpret_cast<LPVOID*>(&fileInfo), &fileInfoSize)) {
                return QString("%1.%2.%3.%4")
                    .arg(HIWORD(fileInfo->dwFileVersionMS))
                    .arg(LOWORD(fileInfo->dwFileVersionMS))
                    .arg(HIWORD(fileInfo->dwFileVersionLS))
                    .arg(LOWORD(fileInfo->dwFileVersionLS));
            }
        }
    }
#endif
    return QString();
}

QString ApplicationManager::getApplicationPublisher(const QString &exePath)
{
    // 这里可以实现获取应用程序发布者的逻辑
    Q_UNUSED(exePath)
    return QString();
}
